#!/usr/bin/env python

import commands, sys
import pprint, smtplib
from ConfigParser import ConfigParser
from optparse import OptionParser

cmdset = { 'svnlook' : '/usr/bin/svnlook' }
class GlobalConfig:
    maillist = {}

def parseLine (line):
    #line = fp.readline()
    if not line:
        return False
    line = line.strip()
    if line.startswith('#'):
        return False

    if line.find('=') == -1 or line.find('@') == -1:
        #print 'Invalid config line:', line
        return False
    toks = line.split('=')
    if len(toks) != 2:
        print 'Multiple delimiters in config line:', line
        return False
    key = toks[0].strip()
    value = toks[1].strip()
    rr = value.split(',')
    if GlobalConfig.maillist.has_key(key):
        GlobalConfig.maillist
        for r in rr:
            r = r.strip()
            if not r in GlobalConfig.maillist[key]:
                GlobalConfig.maillist[key].append(r)
    else:
        GlobalConfig.maillist[key] = []
        for r in rr:
            r = r.strip()
            GlobalConfig.maillist[key].append(r)

    return True


def readConfig(filename, url, sect):
    fp = open(filename, 'r')
    #print filename
    if fp == None:
        print 'File open failed:', file
        return False

	skip = True
    while(1):
        line = fp.readline()

        if not line:
            break
        if line.strip() == '[' + sect + ']':
            skip = False
        elif line.startswith('['):
            skip = True;
            continue
        elif skip:
            continue;

        parseLine( line )

    cmd = 'svn cat ' + url
    stat, out = commands.getstatusoutput( cmd )
    if stat == 0:
        lines = out.split('\n')
    else:
        print 'Getting custom config file failed'
        return False
	skip = True
    for line in lines:
        if line.strip() == '[' + sect + ']':
            skip = False
        elif line.startswith('['):
            skip = True;
            continue
        elif skip:
            continue;

        parseLine( line )
    
    return True
        

def changeset (rev, repos, product):
    changeset = {}
    subset = {}
    subset['rev'] = rev
    subset['changed'] = ''
    subset['author'] = ''
    subset['date'] = ''
    subset['text'] = ''

    cmd = cmdset['svnlook'] + ' changed -r ' + str(rev) + ' ' + repos
    err, out = commands.getstatusoutput (cmd)
    if not err:
        subset['changed'] = out

    cmd = cmdset['svnlook'] + ' author -r' + str(rev) + ' ' + repos
    err, out = commands.getstatusoutput (cmd)
    if not err:
        subset['author'] = out

    cmd = cmdset['svnlook'] + ' log -r' + str(rev) + ' ' + repos
    err, out = commands.getstatusoutput (cmd)
    if not err:
        subset['log'] = out

    cmd = cmdset['svnlook'] + ' date -r' + str(rev) + ' ' + repos
    err, out = commands.getstatusoutput (cmd)
    if not err:
        subset['date'] = out
    subset['repos'] = repos
    subset['product'] = product
    changeset[int(rev)] = subset
    return changeset

def validwildcard(key, onefile):
    if key.strip() == '%':
        return True
    
    if key.endswith('/'):
        key = key[:-1]
    if onefile.endswith('/'):
        onefile = onefile[:-1]

    keytokens = key.split('/')
    filetokens = onefile.split('/')
    if len(keytokens) > len(filetokens):
        return False

    for i in range(0,len(keytokens)):
        if keytokens[i] == filetokens[i]:
            continue
        elif keytokens[i] == '%':
            continue
        else:
            return False

    return True

def notify (changeset):
    mailserver = smtplib.SMTP("localhost")
    SENDMAIL = "/usr/lib/sendmail"
    TRAC = 'http://svnserv1.brass.com/brass/changeset'

    for rev in changeset.keys():
        mailtext = ''
        changed = changeset[rev]['changed']
        log     = changeset[rev]['log']
        date    = changeset[rev]['date']
        author  = changeset[rev]['author']
        mailtext += '\n'
        mailtext += 'Author: ' + author + '\n'
        mailtext += 'Date: ' + date + '\n'
        mailtext += 'Repository: ' + changeset[rev]['repos'] + '\n'
        mailtext += 'Product: ' + changeset[rev]['product'] + '\n'
        mailtext += 'New Revision: ' + str(rev) 
        mailtext += '[<a href=http://svnserv1.brass.com/' + changeset[rev]['product'] + '/changeset/' + str(rev) + '>diff</a>]\n'
        mailtext += '\n'
        chs = changed.split('\n')
        added = ''
        updated = ''
        removed = ''
        fileset = []
        for c in chs:
            if c[0] == 'A':
                added += '\n\t' + c.split()[-1]
                fileset.append(c.split()[-1])
            elif c[0] == 'U':
                updated += '\n\t' + c.split()[-1]
                fileset.append(c.split()[-1])
            elif c[0] == 'D':
                removed += '\n\t' + c.split()[-1]
                fileset.append(c.split()[-1])
            
        if added != ''  : mailtext += '\n\nAdded:' + added
        if updated != '': mailtext += '\n\nModified:' + updated
        if removed != '': mailtext += '\n\nRemoved:' + removed
        mailtext += '\nLog:\n' + log
        mailto = []
        for onefile in fileset:
            for key in GlobalConfig.maillist.keys():
                if onefile.lower().startswith(key) or (key.find('%') != 1 and validwildcard(key.lower(), onefile.lower())):
                    for mid in GlobalConfig.maillist[key]:
                        if not mid in mailto:
                            mailto.append(mid)
                    
        subject = '(' + author + ')' + ' r' + str(rev) + ' in ' + fileset[0]
        if len(mailto) > 0:
            m = ','.join(mailto)
            print 'mailto', mailto
            mailtext += '</pre></html>\n'
            headers = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % ('svn.daemon@brass.com', ','.join(mailto), subject)
            message = 'Subject:[' + author + ']' + subject + '\n' + mailtext + '\n'
            message = 'Content-type: text/html\n<HTML><BODY>' + headers + '<pre>' + mailtext
            mailserver.sendmail ('svn.daemon@brass.com', mailto, message)

def main ():
    Usage = '\t%prog -r REV -p REPOS -c CFGFILE -s SECTION\n'
    parser = OptionParser (usage=Usage)
    parser.add_option ( "-r", "--revision", action="store", help="Revision")
    parser.add_option ( "-p", "--repos", action="store", help="Repository path")
    parser.add_option ( "-c", "--config", action="store", help="Configuration file")
    parser.add_option ( "-s", "--section", action="store", help="Config Section")
    (options, args) = parser.parse_args()

    if (options.revision == None):
       parser.error ('Revision number is missing')
       return False
    elif (options.repos == None):
       parser.error ('Repository path is missing')
       return False
    elif (options.config == None):
       parser.error ('Config file is not specified')
       return False
    elif (options.section == None):
       parser.error ('Config section is not specified')
       return False

    readConfig( options.config, 'svn://svnserv1/tools/svn/trunk/svnutils/mailer/custom.conf', options.section )
    chset = {}
    chset = changeset (options.revision, options.repos, options.section)
    notify (chset)
    return True
    #pprint.pprint (chset)

if __name__ == '__main__':
    main ()
    #stat = validwildcard(sys.argv[1], sys.argv[2])
    #readConfig( sys.argv[1], 'svn://svnserv1/tools/svn/trunk/svnutils/mailer/custom.conf' )
    #pprint.pprint( GlobalConfig.maillist )
    #if stat: print 'Valid wildcard'
    #else: print 'Invalid wildcard'


